package oop.db.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import oop.data.Mark;
import oop.db.Database;

import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;

public class MarkDAO {

	public static List<Mark> fetchByStudentInfo(String name, String surname, String studentId, Date birthday) throws SQLException {
		Connection conn = null;
		PreparedStatement stmt = null;
		ResultSet rs = null;
		try {
			StringBuilder where = new StringBuilder();
			where.append("WHERE (mark_student_name IS NULL OR mark_student_name = '").append(
					StringEscapeUtils.escapeSql(name)).append("')");
			if (!StringUtils.isEmpty(surname)) {
				where.append(" AND (mark_student_surname IS NULL OR mark_student_surname = '").append(
						StringEscapeUtils.escapeSql(surname)).append("')");
			}
			if (!StringUtils.isEmpty(studentId)) {
				where.append(" AND (mark_student_id IS NULL OR mark_student_id = '").append(
						StringEscapeUtils.escapeSql(studentId)).append("')");
			}
			if (birthday != null) {
				DateFormat mysqlDateFormat = new SimpleDateFormat("yyyy-MM-dd");
				where.append(" AND (mark_student_birthday IS NULL OR mark_student_birthday = '").append(
						mysqlDateFormat.format(birthday)).append("')");
			}

			String sql = "SELECT mark_id, mark_version, mark_student_name, "
					+ "mark_student_surname, mark_student_id, "
					+ "mark_student_birthday, mark_mark, mark_exam "
					+ "FROM tblMark " + where;

			conn = Database.get().getConnection();
			stmt = conn.prepareStatement(sql);
			rs = stmt.executeQuery();
	
			return fromResultSet(rs);
		} finally {
			if (rs != null) rs.close();
			if (stmt != null) stmt.close();
			if (conn != null) conn.close();
		}
	}
	
	public static Mark fetchById(long id) throws SQLException {
		Connection conn = null;
		PreparedStatement stmt = null;
		ResultSet rs = null;
		try {
			String sql = "SELECT mark_id, mark_version, mark_student_name, " +
					"mark_student_surname, mark_student_id, " +
					"mark_student_birthday, mark_mark, mark_exam " 
					+ "FROM tblMark "
					+ "WHERE mark_id = ?";

			conn = Database.get().getConnection();
			stmt = conn.prepareStatement(sql);
			stmt.setLong(1, id);
			rs = stmt.executeQuery();
	
			return fromResultSet(rs).get(0);
		} finally {
			if (rs != null) rs.close();
			if (stmt != null) stmt.close();
			if (conn != null) conn.close();
		}
	}

	public static List<Mark> fetchByExamination(long examId)
			throws SQLException {
		Connection conn = null;
		PreparedStatement stmt = null;
		ResultSet rs = null;
		try {
			String sql = "SELECT mark_id, mark_version, mark_student_name, " +
					"mark_student_surname, mark_student_id, " +
					"mark_student_birthday, mark_mark, mark_exam " 
					+ "FROM tblMark "
					+ "WHERE mark_exam = ? " 
					+ "ORDER BY mark_student_name ASC, mark_student_surname ASC";

			conn = Database.get().getConnection();
			stmt = conn.prepareStatement(sql);
			stmt.setLong(1, examId);
			rs = stmt.executeQuery();
	
			return fromResultSet(rs);
		} finally {
			if (rs != null) rs.close();
			if (stmt != null) stmt.close();
			if (conn != null) conn.close();
		}
	}

	public static List<Mark> fetchByExamination(long examId, long start,
			int length) throws SQLException {
		Connection conn = null;
		PreparedStatement stmt = null;
		ResultSet rs = null;
		try {
			String sql = "SELECT mark_id, mark_version, mark_student_name, " +
					"mark_student_surname, mark_student_id, " +
					"mark_student_birthday, mark_mark, mark_exam " 
					+ "FROM tblMark "
					+ "WHERE mark_exam = ? " 
					+ "ORDER BY mark_student_name ASC, mark_student_surname ASC "
					+ "LIMIT ?, ?";

			conn = Database.get().getConnection();
			stmt = conn.prepareStatement(sql);
			stmt.setLong(1, examId);
			stmt.setLong(2, start);
			stmt.setInt(3, length);
			rs = stmt.executeQuery();
	
			return fromResultSet(rs);
		} finally {
			if (rs != null) rs.close();
			if (stmt != null) stmt.close();
			if (conn != null) conn.close();
		}
	}

	public static long countByExamination(long examId) throws SQLException {
		return Database.get().count("SELECT COUNT(*) " +
				"FROM tblMark " +
				"WHERE mark_exam = " + examId);
	}

	public static List<Mark> fromResultSet(ResultSet rs)
			throws SQLException {
		List<Mark> markinations = new ArrayList<Mark>();
		while (rs.next()) {
			markinations.add(new Mark(rs.getLong(1), rs.getLong(2), rs
					.getString(3), rs.getString(4), rs.getString(5), rs
					.getDate(6), rs.getDouble(7), rs.getLong(8)));
		}
		return markinations;
	}

	public static void persist(Mark mark) throws SQLException {
		Connection conn = null;
		PreparedStatement stmt = null;
		try {
				String sql = "UPDATE tblMark SET " +
						"mark_version = ?, mark_student_name = ?, " +
						"mark_student_surname = ?, mark_student_id = ?, " +
						"mark_student_birthday = ?, mark_mark = ? " +
						"WHERE mark_id = ?";

				conn = Database.get().getConnection();
				stmt = conn.prepareStatement(sql);
				stmt.setLong(1, mark.getTestVersion().getId());
				stmt.setString(2, mark.getStudentName());
				if (StringUtils.isEmpty(mark.getStudentSurname())) {
					stmt.setNull(3, Types.VARCHAR);
				} else {
					stmt.setString(3, mark.getStudentSurname());
				}
				if (StringUtils.isEmpty(mark.getStudentId())) {
					stmt.setNull(4, Types.VARCHAR);
				} else {
					stmt.setString(4, mark.getStudentId());
				}
				if (mark.getStudentBirthday() ==  null) {
					stmt.setNull(5, Types.DATE);
				} else {
					stmt.setDate(5, new java.sql.Date(mark.getStudentBirthday().getTime()));
				}
				stmt.setDouble(6, mark.getMark());
				stmt.setLong(7, mark.getId());
				stmt.executeUpdate();
		} finally {
			if (stmt != null) stmt.close();
			if (conn != null) conn.close();
		}
	}

	public static Mark create(long testVersionId, String studentName,
			String studentSurname, String studentId, Date studentBirthday,
			double mark, long examinationId) throws SQLException {
		Connection conn = null;
		PreparedStatement stmt = null;
		ResultSet rs = null;
		try {
			String sql = "INSERT INTO tblMark (mark_exam, " +
					"mark_version, mark_student_name, mark_student_surname, " +
					"mark_student_id, mark_student_birthday, mark_mark) " +
					"VALUES (?, ?, ?, ?, ?, ?, ?)";

			conn = Database.get().getConnection();
			stmt = conn.prepareStatement(sql);
			stmt.setLong(1, examinationId);
			stmt.setLong(2, testVersionId);
			stmt.setString(3, studentName);
			if (StringUtils.isEmpty(studentSurname)) {
				stmt.setNull(4, Types.VARCHAR);
			} else {
				stmt.setString(4, studentSurname);
			}
			if (StringUtils.isEmpty(studentId)) {
				stmt.setNull(5, Types.VARCHAR);
			} else {
				stmt.setString(5, studentId);
			}			
			if (studentBirthday == null) {
				stmt.setNull(6, Types.DATE);
			} else {
				stmt.setDate(6, new java.sql.Date(studentBirthday.getTime()));
			}
			stmt.setDouble(7, mark);
			stmt.executeUpdate();

			rs = stmt.getGeneratedKeys();
			rs.next();
			long id = rs.getLong(1);

			return new Mark(id, testVersionId, studentName, studentSurname,
					studentId, studentBirthday, mark, examinationId);
		} finally {
			if (rs != null) rs.close();
			if (stmt != null) stmt.close();
			if (conn != null) conn.close();
		}
	}

	public static int drop(long markId) throws SQLException {
		Connection conn = null;
		PreparedStatement stmt = null;
		try {
			String sql = "DELETE FROM tblMark " +
					"WHERE mark_id = ?";

			conn = Database.get().getConnection();
			stmt = conn.prepareStatement(sql);
			stmt.setLong(1, markId);
			return stmt.executeUpdate();
		} finally {
			if (stmt != null) stmt.close();
			if (conn != null) conn.close();
		}		
	}

}
